package storemanmpc

import (
	"bytes"
	"crypto/ecdsa"
	"encoding/json"
	"errors"
	"fmt"
	"github.com/btcsuite/btcd/btcec"
	"github.com/btcsuite/btcd/txscript"
	"github.com/wanchain/go-mpc/accounts"
	"github.com/wanchain/go-mpc/accounts/keystore"
	"github.com/wanchain/go-mpc/common"
	"github.com/wanchain/go-mpc/common/hexutil"
	"github.com/wanchain/go-mpc/core/types"
	"github.com/wanchain/go-mpc/crypto"
	"github.com/wanchain/go-mpc/log"
	"github.com/wanchain/go-mpc/p2p"
	"github.com/wanchain/go-mpc/p2p/discover"
	"github.com/wanchain/go-mpc/rlp"
	"github.com/wanchain/go-mpc/storeman/btc"
	"github.com/wanchain/go-mpc/storeman/message"
	"github.com/wanchain/go-mpc/storeman/osmconf"
	schcomm "github.com/wanchain/go-mpc/storeman/schnorrcomm"
	"github.com/wanchain/go-mpc/storeman/schnorrmpc"
	"github.com/wanchain/go-mpc/storeman/schnorrmpcbn"
	mpccrypto "github.com/wanchain/go-mpc/storeman/storemanmpc/crypto"
	mpcprotocol "github.com/wanchain/go-mpc/storeman/storemanmpc/protocol"
	"github.com/wanchain/go-mpc/storeman/validator"
	"gopkg.in/fatih/set.v0"
	"math/big"
	"math/rand"
	"reflect"
	"strconv"
	"sync"
	"time"
)

type MpcContextCreater interface {
	CreateContext(int, uint64, []mpcprotocol.PeerInfo, uint16, uint8, ...MpcValue) (MpcInterface, error) //createContext
	CreateContextUni(ctxType int,
		mpcID uint64,
		peers []mpcprotocol.PeerInfo,
		peerCurCount uint16,
		curveType uint8,
		alg uint8,
		input *mpcprotocol.SignInput,
		preSetValue ...MpcValue) (MpcInterface, error)
}

type MpcValue struct {
	Key       string
	Value     []big.Int
	ByteValue []byte
}

func (v *MpcValue) String() string {
	strRet := "key=" + v.Key
	for i := range v.Value {
		strRet += ", value:" + v.Value[i].String()
	}

	if v.ByteValue != nil {
		strRet += ", value:" + common.ToHex(v.ByteValue)
	}

	return strRet
}

type MpcInterface interface {
	getMessage(*discover.NodeID, *message.MpcMessage, *[]mpcprotocol.PeerInfo) error
	mainMPCProcess(manager mpcprotocol.StoremanManager) error
	getMpcResult(err error) (interface{}, error)
	getMpcResultUni(err error, sigNum int) (interface{}, error)
	quit(error)
	GetGrpIdByCtx() ([]byte, string, error)
}

type P2pMessager interface {
	SendToPeer(*discover.NodeID, uint64, interface{}) error
	IsActivePeer(*discover.NodeID) bool
	GetGroupAlivePeersInfo(groupPeers []mpcprotocol.PeerInfo) ([]mpcprotocol.PeerInfo, error)
}

type mpcAccount struct {
	address      common.Address
	privateShare big.Int
	peers        []mpcprotocol.PeerInfo
	externString string
}

//type KmsInfo struct {
//	AKID      string
//	SecretKey string
//	Region    string
//}
type Storemaner interface {
	Peers() []*p2p.PeerInfo
	PeerIDs() []discover.NodeID
}

type MpcDistributor struct {
	mu         sync.RWMutex
	muKnownMsg sync.RWMutex
	muSntMsg   sync.RWMutex

	Self           *discover.Node
	StoreManGroup  []discover.NodeID
	storeManIndex  map[discover.NodeID]byte
	mpcCreater     MpcContextCreater
	mpcMap         map[uint64]MpcInterface
	AccountManager *accounts.Manager
	P2pMessager    P2pMessager
	accMu          sync.Mutex
	mpcAccountMap  map[common.Address]*mpcAccount
	enableAwsKms   bool
	kmsInfo        osmconf.KmsInfo
	password       string
	knownMsg       *set.Set
	sntMsg         map[interface{}]*set.Set
	storeman       Storemaner
}

func CreateMpcDistributor(accountManager *accounts.Manager,
	msger P2pMessager,
	aKID,
	secretKey,
	region,
	password string,
	storeman Storemaner) *MpcDistributor {

	kmsInfo := osmconf.KmsInfo{aKID, secretKey, region}
	mpc := &MpcDistributor{
		mu:             sync.RWMutex{},
		muKnownMsg:     sync.RWMutex{},
		muSntMsg:       sync.RWMutex{},
		mpcCreater:     &MpcCtxFactory{},
		mpcMap:         make(map[uint64]MpcInterface),
		AccountManager: accountManager,
		accMu:          sync.Mutex{},
		mpcAccountMap:  make(map[common.Address]*mpcAccount),
		kmsInfo:        kmsInfo,
		password:       password,
		P2pMessager:    msger,
		knownMsg:       set.New(),
		sntMsg:         make(map[interface{}]*set.Set),
		storeman:       storeman,
	}

	mpc.enableAwsKms = (aKID != "") && (secretKey != "") && (region != "")

	return mpc
}

func (mpcServer *MpcDistributor) ClearSntKnownMsg() {
	defer mpcServer.muSntMsg.Unlock()
	mpcServer.muSntMsg.Lock()

	for k := range mpcServer.sntMsg {
		delete(mpcServer.sntMsg, k)
	}

	defer mpcServer.muKnownMsg.Unlock()
	mpcServer.muKnownMsg.Lock()
	mpcServer.knownMsg.Clear()
}
func (mpcServer *MpcDistributor) AddSntMsgBatch(hash common.Hash, peerIds []*discover.NodeID) {
	defer mpcServer.muSntMsg.Unlock()
	mpcServer.muSntMsg.Lock()

	if _, has := mpcServer.sntMsg[hash]; !has {
		mpcServer.sntMsg[hash] = set.New()
	}

	for _, peerId := range peerIds {
		peerIdString := peerId.String()
		mpcServer.sntMsg[hash].Add(peerIdString)
	}
}

func (mpcServer *MpcDistributor) AddSntMsg(hash common.Hash, peerId *discover.NodeID) {
	defer mpcServer.muSntMsg.Unlock()
	mpcServer.muSntMsg.Lock()
	if _, has := mpcServer.sntMsg[hash]; !has {
		mpcServer.sntMsg[hash] = set.New()
	}
	mpcServer.sntMsg[hash].Add(peerId.String())
}

func (mpcServer *MpcDistributor) HaveSntMsg(hash common.Hash, peerId *discover.NodeID) bool {
	defer mpcServer.muSntMsg.RUnlock()
	mpcServer.muSntMsg.RLock()

	log.Trace("MpcDistributor", "hash", hash.String(), "peerId", peerId.SlimString(), "set", mpcServer.sntMsg[hash])
	if _, has := mpcServer.sntMsg[hash]; !has {
		return false
	}
	return mpcServer.sntMsg[hash].Has(peerId.String())
}

func (mpcServer *MpcDistributor) GetMsgKnownList(hash common.Hash) (ret []*discover.NodeID) {
	defer mpcServer.muSntMsg.RUnlock()
	mpcServer.muSntMsg.RLock()
	if _, has := mpcServer.sntMsg[hash]; !has {
		return []*discover.NodeID{}
	}
	for _, item := range mpcServer.sntMsg[hash].List() {
		peerIdStr, _ := item.(string)
		peerId, _ := discover.HexID(peerIdStr)
		ret = append(ret, &peerId)
	}
	return
}

func (mpcServer *MpcDistributor) GetMsgSntList(hash common.Hash) (ret []*discover.NodeID) {
	defer mpcServer.muSntMsg.RUnlock()
	mpcServer.muSntMsg.RLock()
	if _, has := mpcServer.sntMsg[hash]; !has {
		return []*discover.NodeID{}
	}
	for _, item := range mpcServer.sntMsg[hash].List() {
		peerIdStr, _ := item.(string)
		peerId, _ := discover.HexID(peerIdStr)
		ret = append(ret, &peerId)
	}
	return
}

func (mpcServer *MpcDistributor) AddToKnown(hash common.Hash) bool {
	// If we reached the memory allowance, drop a previously known transaction hash
	defer mpcServer.muKnownMsg.Unlock()
	mpcServer.muKnownMsg.Lock()
	if !mpcServer.knownMsg.Has(hash) {
		mpcServer.knownMsg.Add(hash)
		return true
	}
	return false
}

func (mpcServer *MpcDistributor) IsKnown(hash common.Hash) bool {
	// If we reached the memory allowance, drop a previously known transaction hash
	defer mpcServer.muKnownMsg.RUnlock()
	mpcServer.muKnownMsg.RLock()
	return mpcServer.knownMsg.Has(hash)
}

func (mpcServer *MpcDistributor) HandleCommon(PeerID *discover.NodeID, msg *p2p.Msg, openSession bool) (*message.MpcMessage, error) {
	// check sig and broadcast
	mpcMessage, err := mpcServer.checkDeepSeaMsg(PeerID, msg, openSession)
	if err != nil {
		return nil, err
	}
	// decriptData
	if err = mpcMessage.DecryptData(); err != nil {
		return nil, err
	}

	// check if the mpcMessage is starting.
	return mpcMessage, nil
}

func (mpcServer *MpcDistributor) HandleCommonBeforeBroadcast(mpcMsg *message.MpcMessage) (*message.MpcMessage, error) {
	// check sig and broadcast
	if mpcMsg == nil {
		return nil, errors.New(fmt.Sprintf("mpcMsg is null"))
	}
	// set outer stepid equal to the inner stepId
	mpcMsg.StepId = uint8(mpcMsg.StepID)

	// add original peerID
	//mpcMsg.OriginPeerId = &mpcServer.Self.ID
	//mpcMsg.OriginPeerId = osmconf.GetOsmConf().IndexByNodeId(mpcServer.Self.ID)
	grpIdStr := hexutil.Encode(mpcMsg.GrpIdBytes)
	mpcMsg.OriginPeerId = osmconf.GetOsmConf().IndexByNodeId(grpIdStr, mpcServer.Self.ID)

	log.SyslogDebug("before encrypt")
	log.SyslogDebug("HandleCommonBeforeBroadcast", "OriginPeerId", mpcMsg.OriginPeerId, "msg", mpcMsg.String())
	for index, item := range mpcMsg.Data {
		log.SyslogDebug("HandleCommonBeforeBroadcast", "index", index, "item", hexutil.Encode(item.Bytes()))
	}

	for index, item := range mpcMsg.BytesData {
		log.SyslogDebug("HandleCommonBeforeBroadcast", "index", index, "itemByte", hexutil.Encode(item))
	}

	// encrypt
	err := mpcMsg.Encypt()
	if err != nil {
		return nil, errors.New(fmt.Sprintf("Encypt mpcMsg error"))
	}
	// add sig

	prv, err := osmconf.GetOsmConf().GetSelfPrvKey()
	if err != nil {
		return nil, errors.New(fmt.Sprintf("mpcMsg GetSelfPrvKey  error"))
	}

	_, err = mpcMsg.BuildHash()
	if err != nil {
		return nil, errors.New(fmt.Sprintf("mpcMsg BuildHash  error %v", err))
	}
	err = mpcMsg.AddKeySig(prv)
	if err != nil {
		return nil, errors.New(fmt.Sprintf("mpcMsg AddKeySig  error"))
	}

	return mpcMsg, nil
}

func (mpcServer *MpcDistributor) updateMsgKnownPeerIds(mpcMsg *message.MpcMessage) {

	hash, _ := mpcMsg.MessageKey()
	var idps []*discover.NodeID
	oldKnownList := mpcMsg.GetKnowPeerIds()

	// sents
	for _, id := range mpcServer.GetMsgSntList(hash) {
		idTemp := *id
		idps = append(idps, &idTemp)
	}
	mpcMsg.AddKnowPeerIds(idps)

	// peers
	ids := mpcServer.storeman.PeerIDs()
	idpPeers := make([]*discover.NodeID, 0)
	for _, id := range ids {
		idTemp := id
		idpPeers = append(idpPeers, &idTemp)
	}
	mpcMsg.AddKnowPeerIds(idpPeers)

	log.SyslogDebug("updateMsgKnownPeerIds",
		"msgHash", hash.String(),
		//"knowlist in mpcmessage [before]", discover.ArrNodeIdpsToStr(oldKnownList),
		//"knowlist in mpcmessage [after]", discover.ArrNodeIdpsToStr(mpcMsg.KnownPeerIds),
		"knowlist in mpcmessage [before]", oldKnownList,
		"knowlist in mpcmessage [after]", mpcMsg.GetKnowPeerIds(),
		"know list in set", discover.ArrNodeIdpsToStr(mpcServer.GetMsgSntList(hash)))
}

func (mpcServer *MpcDistributor) checkDeepSeaMsg(PeerId *discover.NodeID, msg *p2p.Msg, openSession bool) (*message.MpcMessage, error) {
	var mpcMessage message.MpcMessage
	log.Trace("MpcDistributor.checkDeepSeaMsg", "p2p.Msg", msg.String())

	err := rlp.Decode(msg.Payload, &mpcMessage)
	if err != nil {
		log.SyslogErr("MpcDistributor.GetMessage, rlp decode msg fail", "err", err.Error(), "msg", msg.String())
		return nil, err
	}
	log.SyslogDebug("MpcDistributor.GetMessage[checkDeepSeaMsg], mpc message received", "mpcMessage", mpcMessage.String())

	grpIdStr := hexutil.Encode(mpcMessage.GrpIdBytes)

	if !osmconf.GetOsmConf().IsSelfInGroup(grpIdStr) {
		log.SyslogErr("MpcDistributor.GetMessage[checkDeepSeaMsg], IsSelfInGroup false", "mpcMessage", mpcMessage.String(), "grpIdStr", grpIdStr)
		return nil, errors.New(fmt.Sprintf("self is not in the group:%s", grpIdStr))
	} else {
		log.SyslogDebug("MpcDistributor.GetMessage[checkDeepSeaMsg], IsSelfInGroup true", "mpcMessage", mpcMessage.String(), "grpIdStr", grpIdStr)
	}
	// get key
	hash, err := mpcMessage.MessageKey()
	if err != nil {
		log.Error("checkDeepSeaMsg", "MessageKey error", err.Error(), "mpcMessage", mpcMessage.String())
		return nil, err
	}

	// update the known set from the field of the mssage.
	//mpcServer.AddSntMsgBatch(hash, osmconf.GetOsmConf().NodeIdsByUint(mpcMessage.GetKnowPeerIds()))
	mpcServer.AddSntMsgBatch(hash, osmconf.GetOsmConf().NodeIdsByUint(grpIdStr, mpcMessage.GetKnowPeerIds()))

	// duplicate
	if mpcServer.IsKnown(hash) {
		return nil, errors.New(fmt.Sprintf("%s %s", "already has message", mpcMessage.String()))
	}
	// clone for broadcast
	//mpcClone := mpcMessage.Clone()

	if mpcMessage.IsValid() {
		log.Trace("checkDeepSeaMsg is valid", "mpcMessage", mpcMessage.String())

		if !mpcServer.IsKnown(hash) {
			if !mpcServer.AddToKnown(hash) {
				log.SyslogWarning("checkDeepSeaMsg", "AddToKnown", "already AddToKnown", "mpcMessage", mpcMessage.String())
				return nil, errors.New(fmt.Sprintf("%s", "already MarkMsg"))
			}

			forMe, onlyForMe := mpcMessage.IsMyMsg()
			log.SyslogDebug("checkDeepSeaMsg", "forme", forMe, "onlyForMe", onlyForMe, "mpcMessage", mpcMessage.String())
			if forMe && onlyForMe {
				// not broadcast
				return &mpcMessage, nil
			}
			if !forMe {

				var OriginPeerIdBytes discover.NodeID
				//OriginPeerIdBytes = osmconf.GetOsmConf().NodeIdByIndex(mpcMessage.OriginPeerId)
				OriginPeerIdBytes = osmconf.GetOsmConf().NodeIdByIndex(grpIdStr, mpcMessage.OriginPeerId)
				if openSession && bytes.Equal((*mpcServer.SelfNodeId())[:], OriginPeerIdBytes[:]) {
					log.SyslogWarning("checkDeepSeaMsg", "err", "the starter of the session is self", "mpcMessage", mpcMessage.String())
					return nil, errors.New(fmt.Sprintf("%s", "the starter of the seesion is self"))
				}

				var FromPeerIdBytes discover.NodeID
				//FromPeerIdBytes = osmconf.GetOsmConf().NodeIdByIndex(mpcMessage.FromPeerId)
				FromPeerIdBytes = osmconf.GetOsmConf().NodeIdByIndex(grpIdStr, mpcMessage.FromPeerId)
				log.SyslogDebug("checkDeepSeaMsg[!forMe]", "mpcServer.SelfNodeId", mpcServer.SelfNodeId().SlimString(),
					"OriginPeerIdBytes", hexutil.Encode(OriginPeerIdBytes[:]),
					"FromPeerIdBytes", hexutil.Encode(FromPeerIdBytes[:]), "mpcMessage", mpcMessage.String())
				if !bytes.Equal((*mpcServer.SelfNodeId())[:], OriginPeerIdBytes[:]) && !bytes.Equal((*mpcServer.SelfNodeId())[:], FromPeerIdBytes[:]) {
					log.SyslogDebug("checkDeepSeaMsg BroadcastMessage[!forMe]", "message", mpcMessage.String())
					go mpcServer.BroadcastMessage([]discover.NodeID{*PeerId, *mpcServer.SelfNodeId()}, msg.Code, true, &mpcMessage)
				}
				return nil, errors.New(fmt.Sprintf("%s", "is not my msg"))
			}
			if forMe && !onlyForMe {
				// open session and the starter of the seesion is self, not handle the message.
				//go mpcServer.BroadcastMessage([]discover.NodeID{*PeerId, *mpcServer.SelfNodeId()}, msg.Code, true, mpcClone)

				var OriginPeerIdBytes discover.NodeID
				//OriginPeerIdBytes = osmconf.GetOsmConf().NodeIdByIndex(mpcMessage.OriginPeerId)
				OriginPeerIdBytes = osmconf.GetOsmConf().NodeIdByIndex(grpIdStr, mpcMessage.OriginPeerId)
				if openSession && bytes.Equal((*mpcServer.SelfNodeId())[:], OriginPeerIdBytes[:]) {
					log.SyslogWarning("checkDeepSeaMsg", "err", "the starter of the session is self", "mpcMessage", mpcMessage.String())
					return nil, errors.New(fmt.Sprintf("%s", "the starter of the seesion is self"))
				}

				var FromPeerIdBytes discover.NodeID
				//FromPeerIdBytes = osmconf.GetOsmConf().NodeIdByIndex(mpcMessage.FromPeerId)
				FromPeerIdBytes = osmconf.GetOsmConf().NodeIdByIndex(grpIdStr, mpcMessage.FromPeerId)

				log.SyslogDebug("checkDeepSeaMsg[forMe && !onlyForMe]", "mpcServer.SelfNodeId", mpcServer.SelfNodeId().SlimString(),
					"OriginPeerIdBytes", hexutil.Encode(OriginPeerIdBytes[:]),
					"FromPeerIdBytes", hexutil.Encode(FromPeerIdBytes[:]), "mpcMessage", mpcMessage.String())
				bEqualOrig := bytes.Equal((*mpcServer.SelfNodeId())[:], OriginPeerIdBytes[:])
				bEqualFrom := bytes.Equal((*mpcServer.SelfNodeId())[:], FromPeerIdBytes[:])
				log.SyslogDebug("checkDeepSeaMsg BroadcastMessage[for && !onlyForme]", "bEqualOrig", bEqualOrig, "bEqualFrom", bEqualFrom, "message", mpcMessage.String())

				if !bEqualOrig && !bEqualFrom {
					log.SyslogDebug("checkDeepSeaMsg BroadcastMessage[for && !onlyForme]", "message", mpcMessage.String())
					go mpcServer.BroadcastMessage([]discover.NodeID{*PeerId, *mpcServer.SelfNodeId()}, msg.Code, true, &mpcMessage)
				}
				return &mpcMessage, nil
			}
		} else {
			log.SyslogWarning("checkDeepSeaMsg", "err", "already has message1", "mpcMessage", mpcMessage.String())
			return nil, errors.New(fmt.Sprintf("%s", "already has message1"))
		}
	} else {
		log.SyslogErr("checkDeepSeaMsg", "err", "invalid message", "mpcMessage", mpcMessage.String())
		return nil, errors.New(fmt.Sprintf("%s", "invalid message"))
	}

	return nil, errors.New(fmt.Sprintf("%s", "checkDeepSeaMsg unknown error"))
}

func (mpcServer *MpcDistributor) checkDeepSeaMsg1(PeerId *discover.NodeID, msg *p2p.Msg, openSession bool) (*message.MpcMessage, error) {
	var mpcMessage message.MpcMessage
	log.Trace("MpcDistributor.checkDeepSeaMsg", "p2p.Msg", msg.String())

	err := rlp.Decode(msg.Payload, &mpcMessage)
	if err != nil {
		log.SyslogErr("MpcDistributor.GetMessage, rlp decode msg fail", "err", err.Error(), "msg", msg.String())
		return nil, err
	}
	return &mpcMessage, nil
}

func (mpcServer *MpcDistributor) GetMessage(PeerID discover.NodeID, rw p2p.MsgReadWriter, msg *p2p.Msg) error {

	switch msg.Code {

	case mpcprotocol.StatusCode:
		// this should not happen, but no need to panic; just ignore this message.
		log.SyslogInfo("status message received", "peer", PeerID.SlimString())

	case mpcprotocol.KeepaliveCode:
		// this should not happen, but no need to panic; just ignore this message.

	case mpcprotocol.KeepaliveOkCode:
		// this should not happen, but no need to panic; just ignore this message.

	case mpcprotocol.MPCError:

		mpcMessage, err := mpcServer.HandleCommon(&PeerID, msg, false)
		if err != nil {
			return err
		}
		go mpcServer.QuitMpcContext(mpcMessage)

	case mpcprotocol.RequestMPC:
		log.SyslogInfo("MpcDistributor.GetMessage, RequestMPC message received", "peer", PeerID.SlimString())

		mpcMessage, err := mpcServer.HandleCommon(&PeerID, msg, true)
		if err != nil {
			return err
		}
		//create context
		go func() {
			err := mpcServer.createMpcCtx(mpcMessage)

			if err != nil {
				log.SyslogErr("createMpcContext fail", "err", err.Error())
			}
		}()
	case mpcprotocol.RequestMPCUni:
		log.SyslogInfo("MpcDistributor.GetMessage, RequestMPCUni message received", "peer", PeerID.SlimString())

		//create context
		go func() {
			mpcMessage, err := mpcServer.HandleCommon(&PeerID, msg, true)
			if err != nil {
				log.SyslogErr("HandleCommon fail(RequestMPCUni)", "err", err.Error())
				return
			}
			err = mpcServer.createMpcCtxUni(mpcMessage)

			if err != nil {
				log.SyslogErr("createMpcContext fail", "err", err.Error())
			}
		}()
	case mpcprotocol.RequestMPCBtc:
		log.SyslogInfo("MpcDistributor.GetMessage, RequestMPCBtc message received", "peer", PeerID.SlimString())
		mpcMessage, err := mpcServer.HandleCommon(&PeerID, msg, true)
		if err != nil {
			return err
		}
		//create context
		go func() {
			err := mpcServer.createMpcCtxBtc(mpcMessage)

			if err != nil {
				log.SyslogErr("createMpcContext fail", "err", err.Error())
			}
		}()

	case mpcprotocol.MPCMessage:
		go func() {
			mpcMessage, err := mpcServer.HandleCommon(&PeerID, msg, false)
			if err != nil {
				log.SyslogErr("HandleCommon fail(MPCMessage)", "err", err.Error())
				return
			}
			log.SyslogDebug("....call getMpcMessage[GetMessage1]", "mpcMessage", mpcMessage.String())
			go mpcServer.getMpcMessage(&PeerID, mpcMessage)
		}()

	default:
		// New message types might be implemented in the future versions of Whisper.
		// For forward compatibility, just ignore.
	}

	return nil
}

func (mpcServer *MpcDistributor) CreateRequestGPK() (interface{}, error) {
	log.SyslogInfo("CreateRequestGPK begin")

	preSetValue := make([]MpcValue, 0, 1)
	value, err, _ := mpcServer.createRequestMpcContext(mpcprotocol.MpcGPKLeader,
		preSetValue...)

	if err != nil {
		return []byte{}, err
	} else {
		return value, err
	}
}

func (mpcServer *MpcDistributor) CreateReqMpcSign(data []byte, extern []byte, pkBytes []byte, byApprove int64, curveBytes []byte, sendData *mpcprotocol.SendData) (interface{}, error, uint64) {

	log.SyslogInfo("CreateReqMpcSign begin")
	grpId, _ := osmconf.GetOsmConf().GetGrpInxByGpk(pkBytes)

	// MpcGpkBytes stores the gpk bytes.
	grpIdBytes, _ := hexutil.Decode(grpId)
	value, err, mpcID := mpcServer.createRequestMpcContext(mpcprotocol.MpcSignLeader,
		MpcValue{"MpcGrpId", nil, grpIdBytes},
		MpcValue{mpcprotocol.MpcGpkBytes, nil, pkBytes[:]},
		MpcValue{mpcprotocol.PublicKeyResult, nil, pkBytes[:]},
		MpcValue{mpcprotocol.MpcM, nil, data},
		MpcValue{mpcprotocol.MpcExt, nil, extern},
		MpcValue{mpcprotocol.MpcByApprove, []big.Int{*(big.NewInt(byApprove))}, nil},
		MpcValue{mpcprotocol.MpcCurve, nil, curveBytes[:]})

	val, err1 := json.Marshal(&sendData)
	log.SyslogInfo("CreateReqMpcSign begin", "mpcId", mpcID, "@@@@@data for sigin schnorr", string(val))
	if err1 != nil {
		log.SyslogErr("approveOneData, marshal fail", "err", err1.Error())
		return value, err1, mpcID
	}
	return value, err, mpcID
}

func (mpcServer *MpcDistributor) createRequestMpcContext(ctxType int, preSetValue ...MpcValue) (interface{}, error, uint64) {
	log.SyslogInfo("MpcDistributor createRequestMpcContext begin")
	mpcID, err := mpcServer.getMpcID()
	if err != nil {
		return nil, err, 0
	}

	peers := []mpcprotocol.PeerInfo{}

	var grpIdStr string
	for _, item := range preSetValue {
		if item.Key == ("MpcGrpId") {
			grpIdStr = hexutil.Encode(item.ByteValue)
			break
		}
	}

	var curveType uint8
	for _, item := range preSetValue {
		if item.Key == mpcprotocol.MpcCurve {
			curveBig := big.NewInt(0).SetBytes(item.ByteValue)
			curveType = uint8(curveBig.Uint64())
			break
		}
	}

	var smpc mpcprotocol.SchnorrMPCer
	switch int(curveType) {
	case mpcprotocol.SK256Curve:
		smpc = schnorrmpc.NewSkSchnorrMpc()
	case mpcprotocol.BN256Curve:
		smpc = schnorrmpcbn.NewBnSchnorrMpc()
	default:
		smpc = schnorrmpc.NewSkSchnorrMpc()
	}

	var address common.Address
	var gpkString string
	if ctxType == mpcprotocol.MpcSignLeader {
		for _, item := range preSetValue {
			if item.Key == mpcprotocol.MpcGpkBytes {
				pt, err := smpc.UnMarshPt(item.ByteValue)
				if err != nil {
					log.SyslogErr("createRequestMpcContext", "UnMarshPt error", err.Error())

					if !schcomm.PocTest {
						return []byte{}, err, 0
					}
				}
				//address, err = schnorrmpc.PkToAddress(item.ByteValue)
				address, err = smpc.PtToAddress(pt)
				if err != nil {
					log.SyslogErr("createRequestMpcContext", "PtToAddress error", err.Error())

					if !schcomm.PocTest {
						return []byte{}, err, 0
					}
				}
				gpkString = hexutil.Encode(item.ByteValue)
				break
			}
		}

		if schcomm.PocTest {
			b, _ := osmconf.GetOsmConf().GetPrivateShareMock(curveType)

			value := &MpcValue{mpcprotocol.MpcPrivateShare, []big.Int{b}, nil}
			// mpc private share
			preSetValue = append(preSetValue, *value)
		} else {
			addr := common.HexToAddress(gpkString)
			//value, err := mpcServer.loadStoremanAddress(curveType, gpkString, &address)
			value, err := mpcServer.loadStoremanAddress(curveType, gpkString, &addr)
			if err != nil {

				log.SyslogErr("MpcDistributor createRequestMpcContext, loadStoremanAddress fail",
					"address", address.String(),
					"err", err.Error())

				return []byte{}, err, 0
			}

			// mpc private share
			preSetValue = append(preSetValue, *value)
		}
	}

	peers, err = osmconf.GetOsmConf().GetPeersByGrpId(grpIdStr)
	if err != nil {
		log.SyslogErr("createRequestMpcContext", "GetPeersByGrpId", err.Error())
		return nil, err, 0
	}
	groupAlivePeersCount, _ := osmconf.GetOsmConf().GetTotalNum(grpIdStr)
	mpc, err := mpcServer.mpcCreater.CreateContext(ctxType,
		mpcID,
		peers,
		groupAlivePeersCount-1,
		curveType,
		preSetValue...)
	if err != nil {
		log.SyslogErr("MpcDistributor createRequestMpcContext, CreateContext fail", "err", err.Error())
		return []byte{}, err, 0
	}

	log.SyslogInfo("MpcDistributor createRequestMpcContext", "ctxType", ctxType, "mpcID", mpcID)

	mpcServer.addMpcContext(mpcID, mpc)
	defer mpcServer.removeMpcContext(mpcID)
	err = mpc.mainMPCProcess(mpcServer)

	ret, err := mpc.getMpcResult(err)
	return ret, err, mpcID
}

func (mpcServer *MpcDistributor) loadStoremanAddress(curveType uint8, gpkStr string, address *common.Address) (*MpcValue, error) {
	log.SyslogInfo("MpcDistributor.loadStoremanAddress begin", "address", address.String())

	mpcServer.accMu.Lock()
	defer mpcServer.accMu.Unlock()
	value, exist := mpcServer.mpcAccountMap[*address]
	password, _ := osmconf.GetOsmConf().GetGpkPwd(gpkStr)
	var key *keystore.Key
	var err error
	if !exist {
		ks := mpcServer.AccountManager.Backends(keystore.KeyStoreType)[0].(*keystore.KeyStore)
		key, _, err = osmconf.GetPrivateShare(ks, *address, true, &mpcServer.kmsInfo, password)
		if err != nil {
			return nil, err
		}

		value = &mpcAccount{*address, *key.PrivateKey.D, nil, key.Exten}

		mpcServer.mpcAccountMap[*address] = value
	}

	var smpcer mpcprotocol.SchnorrMPCer
	switch int(curveType) {
	case mpcprotocol.SK256Curve:
		smpcer = schnorrmpc.NewSkSchnorrMpc()
	case mpcprotocol.BN256Curve:
		smpcer = schnorrmpcbn.NewBnSchnorrMpc()
	default:
		smpcer = schnorrmpc.NewSkSchnorrMpc()
	}
	gpkShare, _ := smpcer.SkG(&value.privateShare)
	log.SyslogInfo("loadStoremanAddress", "gpkShare", smpcer.PtToHexString(gpkShare))
	//log.SyslogInfo("loadStoremanAddress", "privateShare", hexutil.Encode(value.privateShare.Bytes()))

	return &MpcValue{mpcprotocol.MpcPrivateShare, []big.Int{value.privateShare}, nil}, nil
}

func (mpcServer *MpcDistributor) getMpcID() (uint64, error) {
	var mpcID uint64
	var err error
	for {
		mpcID, err = schcomm.UintRand(uint64(1<<64 - 1))
		if err != nil {
			log.SyslogErr("MpcDistributor getMpcID, UnitRand fail", "err", err.Error())
			return 0, err
		}

		mpcServer.mu.RLock()
		_, exist := mpcServer.mpcMap[mpcID]
		mpcServer.mu.RUnlock()
		if !exist {
			return mpcID, nil
		}
	}
}

func (mpcServer *MpcDistributor) QuitMpcContext(msg *message.MpcMessage) {
	mpcServer.mu.RLock()
	mpc, exist := mpcServer.mpcMap[msg.ContextID]
	mpcServer.mu.RUnlock()
	if exist {
		if len(msg.BytesData) > 0 {
			bytesData := msg.BytesData[0]
			mpc.quit(errors.New(string(bytesData[:])))
		} else {
			mpc.quit(errors.New(string("unknown error")))
		}
	}
}

func (mpcServer *MpcDistributor) createMpcCtx(mpcMessage *message.MpcMessage, preSetValue ...MpcValue) error {
	log.SyslogInfo("MpcDistributor createMpcCtx begin")
	mpcServer.mu.RLock()
	_, exist := mpcServer.mpcMap[mpcMessage.ContextID]
	mpcServer.mu.RUnlock()
	if exist {
		log.SyslogErr("createMpcCtx fail", "err", mpcprotocol.ErrMpcContextExist.Error())
		return mpcprotocol.ErrMpcContextExist
	}

	var ctxType int
	nType := mpcMessage.Data[0].Int64()
	nByApprove := mpcMessage.Data[1].Int64()
	curPeerCount := uint16(mpcMessage.Data[2].Int64())

	if nType == mpcprotocol.MpcGPKLeader {
		ctxType = mpcprotocol.MpcGPKPeer
	} else {

		if nType == mpcprotocol.MpcSignLeader {
			ctxType = mpcprotocol.MpcSignPeer
		} else {
			ctxType = mpcprotocol.MpcSignPeerBtc
		}
	}

	log.SyslogInfo("createMpcCtx", "ctxType", ctxType, "ctxId", mpcMessage.ContextID)
	var grpId string
	var gpkStr string
	var curveType uint8
	if ctxType == mpcprotocol.MpcSignPeer {
		log.SyslogInfo("createMpcCtx MpcSignPeer")
		mpcM := mpcMessage.BytesData[0]
		address := mpcMessage.BytesData[1]
		mpcExt := mpcMessage.BytesData[2]
		curveTypeBytes := mpcMessage.BytesData[3]
		curveType = uint8(big.NewInt(0).SetBytes(curveTypeBytes).Uint64())
		switch int(curveType) {
		case mpcprotocol.SK256Curve:
			//smpc = schnorrmpc.NewSkSchnorrMpc()
		case mpcprotocol.BN256Curve:
			//smpc = schnorrmpcbn.NewBnSchnorrMpc()
		default:
			//smpc = schnorrmpc.NewSkSchnorrMpc()
		}

		gpkStr = hexutil.Encode(address[:])

		log.SyslogInfo("createMpcCtx", "address", address, "mpcM", mpcM)

		var MpcPrivateShare *MpcValue
		var err error

		if schcomm.PocTest {
			b, _ := osmconf.GetOsmConf().GetPrivateShareMock(curveType)
			MpcPrivateShare = &MpcValue{mpcprotocol.MpcPrivateShare, []big.Int{b}, nil}
			// mpc private share
		} else {
			// load account
			addr := common.HexToAddress(gpkStr)
			//MpcPrivateShare, err = mpcServer.loadStoremanAddress(curveType, gpkStr, &add)
			MpcPrivateShare, err = mpcServer.loadStoremanAddress(curveType, gpkStr, &addr)
			if err != nil {
				return err
			}
		}

		grpId, _ = osmconf.GetOsmConf().GetGrpInxByGpk(address[:])
		grpIdBytes, _ := hexutil.Decode(grpId)
		preSetValue = append(preSetValue, MpcValue{"MpcGrpId", nil, grpIdBytes})
		preSetValue = append(preSetValue, MpcValue{mpcprotocol.MpcGpkBytes, nil, address})
		preSetValue = append(preSetValue, MpcValue{mpcprotocol.MpcM, nil, mpcM})
		preSetValue = append(preSetValue, MpcValue{mpcprotocol.MpcExt, nil, mpcExt})
		preSetValue = append(preSetValue, MpcValue{mpcprotocol.MpcCurve, nil, curveTypeBytes})
		preSetValue = append(preSetValue, *MpcPrivateShare)

		receivedData := &mpcprotocol.SendData{PKBytes: address, Data: mpcM[:], Curve: curveTypeBytes, Extern: string(mpcExt[:])}
		log.SyslogInfo("@@@@@received schnorr message", receivedData.String(), "ctxId", mpcMessage.ContextID)

		//rcvData = receivedData
		if nByApprove != 0 {
			addApprovingResult := validator.AddApprovingData(receivedData)
			if addApprovingResult != nil {
				var buf bytes.Buffer
				buf.Write([]byte(mpcprotocol.ErrFailedAddApproving.Error()))

				mpcMsg := &message.MpcMessage{ContextID: mpcMessage.ContextID,
					StepID: 0}

				// send error message to self and kill self.
				mpcMsg.PeerID = &mpcServer.Self.ID
				mpcMsg.BytesData = append(mpcMsg.BytesData, buf.Bytes())

				mpcServer.P2pMessage(&mpcServer.Self.ID, mpcprotocol.MPCError, mpcMsg)

				log.SyslogErr("createMpcContext, AddApprovingData  fail",
					"ContextID", mpcMessage.ContextID, "err", addApprovingResult.Error())
				return mpcprotocol.ErrFailedAddApproving
			}
		}

		verifyResult, err := validator.ValidateData(receivedData)

		if !verifyResult {
			log.SyslogErr("createMpcContext, verify data fail", "ContextID", mpcMessage.ContextID, "err", err.Error())

			var buf bytes.Buffer
			buf.Write([]byte(mpcprotocol.ErrVerifyFailed.Error()))

			mpcMsg := &message.MpcMessage{ContextID: mpcMessage.ContextID,
				StepID: 0}
			mpcMsg.PeerID = &mpcServer.Self.ID
			mpcMsg.BytesData = append(mpcMsg.BytesData, buf.Bytes())

			mpcServer.P2pMessage(&mpcServer.Self.ID, mpcprotocol.MPCError, mpcMsg)

			return err
		}

	} else if ctxType == mpcprotocol.MpcGPKPeer {
		log.SyslogInfo("createMpcCtx", "ctxType", ctxType)
	}

	var originPeerIdBytes discover.NodeID
	//originPeerIdBytes = osmconf.GetOsmConf().NodeIdByIndex(mpcMessage.OriginPeerId)
	originPeerIdBytes = osmconf.GetOsmConf().NodeIdByIndex(grpId, mpcMessage.OriginPeerId)
	isFromLeader, err := osmconf.GetOsmConf().IsFromLeader(grpId, &originPeerIdBytes)
	if err != nil {
		return err
	}
	if !isFromLeader {
		log.SyslogErr("createMpcCtx", "err", mpcprotocol.ErrSignreqNotFromLeader.Error(), "fromId", mpcMessage.OriginPeerId)
		return mpcprotocol.ErrSignreqNotFromLeader
	}

	msgPeers, err := osmconf.GetOsmConf().GetPeersByGrpId(grpId)
	if err != nil {
		log.SyslogErr("createMpcContext, createContext fail", "err", err.Error())
		return err
	}

	mpc, err := mpcServer.mpcCreater.CreateContext(ctxType,
		mpcMessage.ContextID,
		msgPeers,
		curPeerCount,
		uint8(curveType),
		preSetValue...)

	if err != nil {
		log.SyslogErr("createMpcContext, createContext fail", "err", err.Error())
		return err
	}

	go func() {
		mpcServer.addMpcContext(mpcMessage.ContextID, mpc)
		//defer validator.DeleteData(rcvData)
		defer mpcServer.removeMpcContext(mpcMessage.ContextID)
		err = mpc.mainMPCProcess(mpcServer)
	}()

	return nil
}

func (mpcServer *MpcDistributor) createMpcCtxUni(mpcMessage *message.MpcMessage, preSetValue ...MpcValue) error {
	log.SyslogInfo("MpcDistributor createMpcCtxUni begin")
	mpcServer.mu.RLock()
	_, exist := mpcServer.mpcMap[mpcMessage.ContextID] //todo add throat to handle burst traffic.
	mpcServer.mu.RUnlock()
	if exist {
		log.SyslogErr("createMpcCtxUni fail", "err", mpcprotocol.ErrMpcContextExist.Error())
		return mpcprotocol.ErrMpcContextExist
	}

	var ctxType int
	nType := mpcMessage.Data[0].Int64()
	nByApprove := mpcMessage.Data[1].Int64()
	curPeerCount := uint16(mpcMessage.Data[2].Int64())

	if nType == mpcprotocol.MpcGPKLeader {
		ctxType = mpcprotocol.MpcGPKPeer
	} else {

		if nType == mpcprotocol.MpcSignLeaderUni {
			ctxType = mpcprotocol.MpcSignPeerUni
		}
	}

	log.SyslogInfo("createMpcCtxUni", "ctxType", ctxType, "ctxId", mpcMessage.ContextID)
	var grpId string
	var gpkStr string
	var curveType uint8
	var alg uint8
	var input mpcprotocol.SignInput

	if ctxType == mpcprotocol.MpcSignPeerUni {

		log.SyslogInfo("createMpcCtx MpcSignPeer")
		gpkBytes := mpcMessage.BytesData[0]

		err := rlp.DecodeBytes(mpcMessage.BytesData[1], &input)
		if err != nil {
			log.SyslogErr("createMpcCtxUni", "decode input error", err.Error())
			return err
		}
		curveType = uint8(big.NewInt(0).SetBytes(input.Curve).Uint64())
		alg = uint8(big.NewInt(0).SetBytes(input.Alg).Uint64())
		var smpc mpcprotocol.SchnorrMPCer

		switch int(curveType) {
		case mpcprotocol.SK256Curve:
			smpc = schnorrmpc.NewSkSchnorrMpc()
		case mpcprotocol.BN256Curve:
			smpc = schnorrmpcbn.NewBnSchnorrMpc()
		default:
			smpc = schnorrmpc.NewSkSchnorrMpc()
		}

		gpkStr = hexutil.Encode(gpkBytes[:])

		log.SyslogInfo("createMpcCtxUni", "gpk", gpkStr)

		var MpcPrivateShare *MpcValue

		if schcomm.PocTest {
			b, _ := osmconf.GetOsmConf().GetPrivateShareMock(curveType)
			MpcPrivateShare = &MpcValue{mpcprotocol.MpcPrivateShare, []big.Int{b}, nil}
			// mpc private share
		} else {
			// load account
			addr := common.HexToAddress(gpkStr)
			//MpcPrivateShare, err = mpcServer.loadStoremanAddress(curveType, gpkStr, &add)
			MpcPrivateShare, err = mpcServer.loadStoremanAddress(curveType, gpkStr, &addr)
			if err != nil {
				return err
			}

			// mpc private share
			preSetValue = append(preSetValue, *MpcPrivateShare)

			// mpc private share inverse
			skInverse, _ := smpc.NSubX(&MpcPrivateShare.Value[0])
			valueInverse := &MpcValue{mpcprotocol.MpcPrivateShareInverse, []big.Int{*skInverse}, nil}
			preSetValue = append(preSetValue, *valueInverse)
		}

		grpId, _ = osmconf.GetOsmConf().GetGrpInxByGpk(gpkBytes[:])
		grpIdBytes, _ := hexutil.Decode(grpId)
		preSetValue = append(preSetValue, MpcValue{"MpcGrpId", nil, grpIdBytes})
		preSetValue = append(preSetValue, MpcValue{mpcprotocol.MpcGpkBytes, nil, gpkBytes})

		log.SyslogInfo("@@@@@received signByApprove message", input.String(), "ctxId", mpcMessage.ContextID)

		//rcvData = receivedData
		if nByApprove != 0 {
			addApprovingResult := validator.AddApprovingDataUni(&input)
			if addApprovingResult != nil {
				var buf bytes.Buffer
				buf.Write([]byte(mpcprotocol.ErrFailedAddApproving.Error()))

				mpcMsg := &message.MpcMessage{ContextID: mpcMessage.ContextID,
					StepID: 0}

				// send error message to self and kill self.
				mpcMsg.PeerID = &mpcServer.Self.ID
				mpcMsg.BytesData = append(mpcMsg.BytesData, buf.Bytes())

				mpcServer.P2pMessage(&mpcServer.Self.ID, mpcprotocol.MPCError, mpcMsg)

				log.SyslogErr("createMpcContext, AddApprovingData  fail",
					"ContextID", mpcMessage.ContextID, "err", addApprovingResult.Error(), "input", input.String())
				return mpcprotocol.ErrFailedAddApproving
			}
		}

		verifyResult, err := validator.ValidateDataUni(&input)

		if !verifyResult {
			log.SyslogErr("createMpcContext, verify data fail", "ContextID", mpcMessage.ContextID, "err", err.Error())

			var buf bytes.Buffer
			buf.Write([]byte(mpcprotocol.ErrVerifyFailed.Error()))

			mpcMsg := &message.MpcMessage{ContextID: mpcMessage.ContextID,
				StepID: 0}
			mpcMsg.PeerID = &mpcServer.Self.ID
			mpcMsg.BytesData = append(mpcMsg.BytesData, buf.Bytes())

			mpcServer.P2pMessage(&mpcServer.Self.ID, mpcprotocol.MPCError, mpcMsg)

			return err
		}

	} else if ctxType == mpcprotocol.MpcGPKPeer {
		log.SyslogInfo("createMpcCtx", "ctxType", ctxType)
	}

	//isFromLeader, err := osmconf.GetOsmConf().IsFromLeader(grpId, mpcMessage.OriginPeerId)
	var OriginPeerIdBytes discover.NodeID
	//OriginPeerIdBytes = osmconf.GetOsmConf().NodeIdByIndex(mpcMessage.OriginPeerId)
	OriginPeerIdBytes = osmconf.GetOsmConf().NodeIdByIndex(grpId, mpcMessage.OriginPeerId)
	isFromLeader, err := osmconf.GetOsmConf().IsFromLeader(grpId, &OriginPeerIdBytes)
	if err != nil {
		return err
	}
	if !isFromLeader {
		log.SyslogErr("createMpcCtx", "err", mpcprotocol.ErrSignreqNotFromLeader.Error(), "fromId", mpcMessage.OriginPeerId)
		return mpcprotocol.ErrSignreqNotFromLeader
	}

	msgPeers, err := osmconf.GetOsmConf().GetPeersByGrpId(grpId)
	if err != nil {
		log.SyslogErr("createMpcContext, createContext fail", "err", err.Error())
		return err
	}

	mpc, err := mpcServer.mpcCreater.CreateContextUni(
		ctxType,
		mpcMessage.ContextID,
		msgPeers,
		curPeerCount,
		uint8(curveType),
		uint8(alg),
		&input,
		preSetValue...)

	if err != nil {
		log.SyslogErr("createMpcContext, createContext fail", "err", err.Error())
		return err
	}

	go func() {
		mpcServer.addMpcContext(mpcMessage.ContextID, mpc)
		//defer validator.DeleteData(rcvData)
		defer mpcServer.removeMpcContext(mpcMessage.ContextID)
		err = mpc.mainMPCProcess(mpcServer)
	}()

	return nil
}

func (mpcServer *MpcDistributor) createMpcCtxBtc(mpcMessage *message.MpcMessage, preSetValue ...MpcValue) error {
	log.SyslogInfo("MpcDistributor createMpcCtxBtc begin", "mpc message", mpcMessage.String())

	mpcServer.mu.RLock()
	_, exist := mpcServer.mpcMap[mpcMessage.ContextID]
	mpcServer.mu.RUnlock()
	if exist {
		log.SyslogErr("createMpcCtxBtc fail", "err", mpcprotocol.ErrMpcContextExist.Error())
		return mpcprotocol.ErrMpcContextExist
	}

	var ctxType int
	nType := mpcMessage.Data[0].Int64()
	curPeerCount := uint16(mpcMessage.Data[4].Int64())

	nByApprove := mpcMessage.Data[5].Int64()

	if nType == mpcprotocol.MpcGPKLeader {
		ctxType = mpcprotocol.MpcGPKPeer
	} else {

		if nType == mpcprotocol.MpcSignLeaderBtc {
			ctxType = mpcprotocol.MpcSignPeerBtc
		}
	}

	log.SyslogInfo("createMpcCtxBtc", "ctxType", ctxType, "ctxId", mpcMessage.ContextID)
	var grpId string
	var curveType uint8

	if ctxType == mpcprotocol.MpcSignPeerBtc {
		log.SyslogInfo("createMpcContext MpcSignPeerBtc")

		chainType := string(mpcMessage.BytesData[0])
		txBytesData := mpcMessage.BytesData[1]
		txSignType := mpcMessage.BytesData[2]

		curveTypeBytes := mpcMessage.BytesData[3]
		curveType = uint8(big.NewInt(0).SetBytes(curveTypeBytes).Uint64())

		gpkBytes := mpcMessage.BytesData[4]
		gpkStr := hexutil.Encode(gpkBytes[:])

		txHash := mpcMessage.Data[1]
		address := common.BigToAddress(&mpcMessage.Data[2])
		chainId := mpcMessage.Data[3]

		log.SyslogInfo(
			">>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>createMpcCtxBtc",
			"chainType", string(chainType),
			"txData", common.ToHex(txBytesData),
			"signType", string(txSignType),
			"txHash", txHash.String(),
			"address", address.String(),
			"chainId", chainId.String(),
			"peerCount", curPeerCount)

		// load account
		addr := common.HexToAddress(gpkStr)
		//MpcPrivateShare, err = mpcServer.loadStoremanAddress(curveType, gpkStr, &add)
		MpcPrivateShare, err := mpcServer.loadStoremanAddress(curveType, gpkStr, &addr)
		if err != nil {
			return err
		}

		grpId, _ = osmconf.GetOsmConf().GetGrpInxByGpk(gpkBytes[:])

		var OriginPeerIdBytes discover.NodeID
		//OriginPeerIdBytes = osmconf.GetOsmConf().NodeIdByIndex(mpcMessage.OriginPeerId)
		OriginPeerIdBytes = osmconf.GetOsmConf().NodeIdByIndex(grpId, mpcMessage.OriginPeerId)

		isFromLeader, err := osmconf.GetOsmConf().IsFromLeader(grpId, &OriginPeerIdBytes)
		if err != nil {
			return err
		}
		if !isFromLeader {
			log.SyslogErr("createMpcCtxBtc", "err", mpcprotocol.ErrSignreqNotFromLeader.Error(), "fromId", mpcMessage.OriginPeerId)
			return mpcprotocol.ErrSignreqNotFromLeader
		}
		grpIdBytes, _ := hexutil.Decode(grpId)
		preSetValue = append(preSetValue, MpcValue{"MpcGrpId", nil, grpIdBytes})
		preSetValue = append(preSetValue, MpcValue{mpcprotocol.MpcGpkBytes, nil, gpkBytes})
		preSetValue = append(preSetValue, MpcValue{mpcprotocol.MpcCurve, nil, curveTypeBytes})

		preSetValue = append(preSetValue, MpcValue{mpcprotocol.MpcChainType, nil, []byte(chainType)})
		preSetValue = append(preSetValue, MpcValue{mpcprotocol.MpcAddress, []big.Int{*address.Big()}, nil})
		preSetValue = append(preSetValue, MpcValue{mpcprotocol.MpcTransaction, nil, txBytesData})

		if chainType == "BTC" {
			var btcTx btc.MsgTxArgs
			err = rlp.DecodeBytes(txBytesData, &btcTx)
			if err != nil {
				log.SyslogErr("createMpcCtxBtc, rlp decode tx fail", "err", err.Error())
				return err
			}
			log.SyslogInfo("createMpcCtxBtc", "@@@@@received btc message", btcTx.String(), "ctxId", mpcMessage.ContextID)
			if nByApprove != 0 {
				addApprovingResult := validator.AddApprovingBtcTran(&btcTx)
				if addApprovingResult != nil {

					var buf bytes.Buffer
					buf.Write([]byte(mpcprotocol.ErrFailedAddApproving.Error()))

					mpcMsg := &message.MpcMessage{ContextID: mpcMessage.ContextID,
						StepID: 0}

					mpcMsg.PeerID = &mpcServer.Self.ID
					mpcMsg.BytesData = append(mpcMsg.BytesData, buf.Bytes())
					mpcServer.P2pMessage(&mpcServer.Self.ID, mpcprotocol.MPCError, mpcMsg)

					log.SyslogErr("createMpcCtxBtc, AddApprovingBtc  fail",
						"ContextID", mpcMessage.ContextID, "err", addApprovingResult.Error())
					return mpcprotocol.ErrAddApprovingBtcTran
				}
				log.SyslogInfo("createMpcCtxBtc AddApprovingBtcTran successfully")
			}

			verifyResult := validator.ValidateBtcTx(&btcTx)
			if !verifyResult {

				log.SyslogErr("createMpcContext, verify tx fail", "ContextID", mpcMessage.ContextID)
				return mpcprotocol.ErrFailedTxVerify
			}

			txHashes, err := btc.GetHashedForEachTxIn(&btcTx)
			if err != nil {
				log.SyslogErr("createMpcContext, GetHashedForEachTxIn fail", "err", err.Error())
				return err
			}

			for i := 0; i < len(btcTx.TxIn); i++ {
				preSetValue = append(preSetValue, MpcValue{mpcprotocol.MpcTxHash + "_" + strconv.Itoa(i), []big.Int{*txHashes[i].Big()}, nil})
			}
		} else if chainType == "DOT" {

			log.SyslogInfo("createMpcCtxBtc", "@@@@@received dot message", string(txBytesData), "ctxId", mpcMessage.ContextID)
			if nByApprove != 0 {
				addApprovingResult := validator.AddApprovingDotTran(txBytesData)
				if addApprovingResult != nil {

					var buf bytes.Buffer
					buf.Write([]byte(mpcprotocol.ErrFailedAddApproving.Error()))

					mpcMsg := &message.MpcMessage{ContextID: mpcMessage.ContextID,
						StepID: 0}

					mpcMsg.PeerID = &mpcServer.Self.ID
					mpcMsg.BytesData = append(mpcMsg.BytesData, buf.Bytes())
					mpcServer.P2pMessage(&mpcServer.Self.ID, mpcprotocol.MPCError, mpcMsg)

					log.SyslogErr("createMpcCtxBtc, AddApprovingBtc  fail",
						"ContextID", mpcMessage.ContextID, "err", addApprovingResult.Error())
					return mpcprotocol.ErrAddApprovingBtcTran
				}
				log.SyslogInfo("createMpcCtxBtc AddApprovingBtcTran successfully")
			}

			verifyResult := validator.ValidateDotTx(txBytesData)
			if !verifyResult {

				log.SyslogErr("createMpcContext, verify Dot tx fail", "ContextID", mpcMessage.ContextID)
				return mpcprotocol.ErrFailedTxVerify
			}

			preSetValue = append(preSetValue, MpcValue{mpcprotocol.MpcTxHash + "_0", []big.Int{txHash}, nil})
			preSetValue = append(preSetValue, MpcValue{mpcprotocol.MpcSignType, nil, []byte("hash")})
		} else {

			hd, err := validator.GetHandlerByChain(chainType, txHash.Bytes(), txBytesData)
			if err != nil {
				log.SyslogErr("GetHandlerByChain fail", "ContextID", mpcMessage.ContextID)
				return err
			}
			xrpHd, ok := hd.(*validator.XrpTxHandler)
			if ok {
				log.SyslogInfo("createMpcCtxBtc", "@@@@@received Xrp message", xrpHd.String(), "ctxId", mpcMessage.ContextID)
			}
			verifyResult := hd.ValidateTx()
			if !verifyResult {

				log.SyslogErr("createMpcContext, verify tx fail", "ContextID", mpcMessage.ContextID)
				return mpcprotocol.ErrFailedTxVerify
			}

			txHashes := hd.GetHashedData()
			for i := 0; i < len(txHashes); i++ {

				hash := common.BytesToHash(txHashes[i])
				preSetValue = append(preSetValue, MpcValue{mpcprotocol.MpcTxHash + "_" + strconv.Itoa(i), []big.Int{*hash.Big()}, nil})
			}
		}

		preSetValue = append(preSetValue, *MpcPrivateShare)
		preSetValue = append(preSetValue, MpcValue{mpcprotocol.MpcSignType, nil, []byte("hash")})

	} else {
		log.SyslogInfo("createMpcCtx", "ctxType", ctxType)
	}

	msgPeers, err := osmconf.GetOsmConf().GetPeersByGrpId(grpId)
	if err != nil {
		log.SyslogErr("createMpcContext, createContext fail", "err", err.Error())
		return err
	}

	mpc, err := mpcServer.mpcCreater.CreateContext(ctxType,
		mpcMessage.ContextID,
		msgPeers,
		curPeerCount,
		uint8(curveType),
		preSetValue...)

	if err != nil {
		log.SyslogErr("createMpcContext, createContext fail", "err", err.Error())
		return err
	}

	go func() {
		mpcServer.addMpcContext(mpcMessage.ContextID, mpc)
		defer mpcServer.removeMpcContext(mpcMessage.ContextID)
		err = mpc.mainMPCProcess(mpcServer)
	}()

	return nil
}

func (mpcServer *MpcDistributor) addMpcContext(mpcID uint64, mpc MpcInterface) {
	log.SyslogInfo("addMpcContext", "ctxId", mpcID)

	mpcServer.mu.Lock()
	defer mpcServer.mu.Unlock()
	mpcServer.mpcMap[mpcID] = mpc
}

func (mpcServer *MpcDistributor) removeMpcContext(mpcID uint64) {
	log.SyslogInfo("removeMpcContext", "ctxId", mpcID)

	mpcServer.mu.Lock()
	defer mpcServer.mu.Unlock()
	delete(mpcServer.mpcMap, mpcID)
}

func (mpcServer *MpcDistributor) getMpcMessage(PeerID *discover.NodeID, mpcMessage *message.MpcMessage) error {
	log.SyslogInfo("......getMpcMessage", "mpcMessage", mpcMessage.String()) //todo restore level

	mpcServer.mu.RLock()
	mpc, exist := mpcServer.mpcMap[mpcMessage.ContextID]
	mpcServer.mu.RUnlock()
	if exist {
		//return mpc.getMessage(PeerID, mpcMessage, nil)
		go mpc.getMessage(PeerID, mpcMessage, nil)
	}

	return nil
}

func (mpcServer *MpcDistributor) getOwnerP2pMessage(PeerID *discover.NodeID, code uint64, msg interface{}) error {
	log.SyslogDebug("Entering MpcDistributor.getOwnerP2pMessage", "peerId", PeerID.SlimString())
	switch code {
	case mpcprotocol.MPCMessage:
		mpcMessage := msg.(*message.MpcMessage)
		log.SyslogDebug("....call getMpcMessage[getOwnerP2pMessage]", "mpcMessage", mpcMessage.String())
		key, err := mpcMessage.MessageKey()
		if err != nil {
			return err
		}

		// fix issue for message send to itself twice
		if !mpcServer.IsKnown(key) {
			if !mpcServer.AddToKnown(key) {
				return nil
			}
			mpcServer.getMpcMessage(PeerID, mpcMessage)
		}

	case mpcprotocol.RequestMPCNonce:
		// do nothing
	default:
		log.SyslogDebug("getOwnerP2pMessage", "messagecode", code)
		return nil
	}

	return nil
}

func (mpcServer *MpcDistributor) SelfNodeId() *discover.NodeID {
	return &mpcServer.Self.ID
}

func (mpcServer *MpcDistributor) P2pMessage(peerID *discover.NodeID, code uint64, msg interface{}) error {
	if *peerID == mpcServer.Self.ID {
		mpcServer.getOwnerP2pMessage(&mpcServer.Self.ID, code, msg)
	} else {
		err := mpcServer.P2pMessager.SendToPeer(peerID, code, msg)
		if err != nil {
			log.SyslogErr("BroadcastMessage fail", "err", err.Error())
		}
	}

	return nil
}

func IsHaming(all, index uint64) bool {
	if all == uint64(0) {
		return false
	}

	exist := all & (1 << index)
	if exist != uint64(0) {
		return true
	}
	return false
}

func (mpcServer *MpcDistributor) BroadcastMessage(peersExcept []discover.NodeID, code uint64, isTransfer bool, msg interface{}) error {
	// replace peerId from nil to NIlNodeId
	var hash common.Hash
	var originPeerID *discover.NodeID

	var mpcMsg *message.MpcMessage

	mpcMsg, ok := msg.(*message.MpcMessage)
	if !ok {
		log.Error("BroadcastMessage", "convert to MpcMessage error.", "not mpc message", "msg", fmt.Sprintf("%#v", msg))
		return errors.New("not mpc message")
	}

	grpIdStr := hexutil.Encode(mpcMsg.GrpIdBytes)

	if mpcMsg.PeerID == nil {
		mpcMsg.PeerID = mpcprotocol.GetNilNodeId()
	}
	log.Debug("BroadcastMessage [Entering]", "msg", mpcMsg.String())
	//hash, _ = mpcMsg.MessageKey()

	oldKnowList := mpcMsg.GetKnowPeerIds()
	// update the from peerID
	mpcMsg.UpdateFromPeerID(osmconf.GetOsmConf().SelfNodeId)
	//mpcServer.updateMsgKnownPeerIds(mpcMsg)    //should update after send peer successfully.

	// not transfer, the original of the message.
	if !isTransfer {
		mpcMessage, err := mpcServer.HandleCommonBeforeBroadcast(mpcMsg)
		if err != nil {
			log.SyslogErr("BroadcastMessage", "HandleCommonBeforeBroadcast error", err.Error())
			return err
		}
		msg = mpcMessage
	}

	hash, _ = mpcMsg.MessageKey()
	mpcServer.updateMsgKnownPeerIds(mpcMsg) // move to here because handleCommonBeforeXXX change hash of msg.

	mpcMsgStr := mpcMsg.String()

	//originPeerID = mpcMsg.OriginPeerId
	//var originPeerIDBytes = osmconf.GetOsmConf().NodeIdByIndex(mpcMsg.OriginPeerId)
	var originPeerIDBytes = osmconf.GetOsmConf().NodeIdByIndex(grpIdStr, mpcMsg.OriginPeerId)
	log.SyslogDebug("BroadcastMessage-originPeerIDBytes", "originPeerIDBytes", originPeerIDBytes.SlimString(), "msg", mpcMsg.String())
	originPeerID = &originPeerIDBytes
	log.SyslogDebug("BroadcastMessage-originPeerID", "originPeerID", originPeerID.SlimString(), "msg", mpcMsg.String())

	peMap := make(map[discover.NodeID]bool)
	for index, peerId := range peersExcept {
		log.SyslogDebug("BroadcastMessage-peersExcept", "index", index, "peer", peerId.SlimString(), "msg", mpcMsg.String())
		peMap[peerId] = true
	}

	// add bootnode in expection
	bootNode := osmconf.GetOsmConf().GetBootNodeID()
	if bootNode != nil {
		log.SyslogDebug("BroadcastMessage-peersExcept", "bootNode", bootNode.SlimString(), "msg", mpcMsg.String())
		peMap[*bootNode] = true
	}

	if originPeerID != nil {
		log.SyslogDebug("BroadcastMessage-originPeerID", "originPeerID", "isTransfer", isTransfer, originPeerID.SlimString(), "msg", mpcMsg.String())
		if isTransfer {
			peMap[*originPeerID] = true
		}
	}

	// broad cast need send message to itself, too.
	ids := mpcServer.storeman.PeerIDs()
	ids = append(ids, mpcServer.Self.ID)
	for index, id := range ids {
		log.SyslogDebug("BroadcastMessage-ids", "index", index, "peer", id.SlimString(), "msg", mpcMsg.String())
	}
	myPeerMap := make(map[discover.NodeID]bool)
	for _, id := range ids {
		myPeerMap[id] = true
	}

	// self send to self,no need to broadcast
	var orignPeerIdBytes discover.NodeID
	//orignPeerIdBytes = osmconf.GetOsmConf().NodeIdByIndex(mpcMsg.OriginPeerId)
	orignPeerIdBytes = osmconf.GetOsmConf().NodeIdByIndex(grpIdStr, mpcMsg.OriginPeerId)
	if bytes.Equal(orignPeerIdBytes[:], (*mpcMsg.PeerID)[:]) && bytes.Equal(orignPeerIdBytes[:], (mpcServer.Self.ID)[:]) {
		log.SyslogDebug("BroadcastMessage successfully(p2p getOwnerP2pMessage)", "isTransfer", isTransfer, "peer", mpcMsg.PeerID.SlimString(), "msg", mpcMsg.String())
		mpcServer.getOwnerP2pMessage(&mpcServer.Self.ID, code, msg)
		return nil
	}

	// peer to peer message, and the destination peer in the peersMap, no need to broadcast
	if _, ok := myPeerMap[*mpcMsg.PeerID]; ok {
		err := mpcServer.P2pMessager.SendToPeer(mpcMsg.PeerID, code, msg)
		if err != nil {
			log.SyslogErr("BroadcastMessage fail(p2p)", "peer", mpcMsg.PeerID.SlimString(), "err", err.Error())

			time.Sleep(time.Millisecond * time.Duration(rand.Intn(20)))
			err2 := mpcServer.P2pMessager.SendToPeer(mpcMsg.PeerID, code, msg)
			if err2 != nil {
				log.SyslogErr("BroadcastMessage fail again(p2p)", "peer", mpcMsg.PeerID.SlimString(), "err", err.Error())
			} else {
				log.SyslogInfo("BroadcastMessage successfully(p2p retry)", "isTransfer", isTransfer, "peer", mpcMsg.PeerID.SlimString(), "msg", mpcMsgStr)
				mpcServer.AddSntMsg(hash, mpcMsg.PeerID)
				//mpcServer.updateMsgKnownPeerIds(mpcMsg)
			}

		} else {
			log.SyslogInfo("BroadcastMessage successfully(p2p)", "isTransfer", isTransfer, "peer", mpcMsg.PeerID.SlimString(), "msg", mpcMsgStr)
			// sent successfully and update the sntMsg to prevent send msg again.
			mpcServer.AddSntMsg(hash, mpcMsg.PeerID)
			//mpcServer.updateMsgKnownPeerIds(mpcMsg)
		}
		return nil
	}

	var haveSntIdps []*discover.NodeID
	var SendIdps []*discover.NodeID

	for index, id := range ids {
		tempId := discover.NodeID{}
		copy(tempId[:], id[:])
		// the nodeId should not to be sent
		if _, ok := peMap[id]; ok {
			log.SyslogDebug("BroadcastMessage successfully(peMap)", "isTransfer", isTransfer, "index", index, "peer", id.SlimString(), "msg", mpcMsg.String())
			continue
		}

		// self id
		if id == mpcServer.Self.ID {
			SendIdps = append(SendIdps, &id)
			mpcServer.getOwnerP2pMessage(&mpcServer.Self.ID, code, msg)
			log.SyslogDebug("BroadcastMessage successfully(getOwnerP2pMessage)", "isTransfer", isTransfer, "index", index, "peer", id.SlimString(), "msg", mpcMsg.String())
		} else {
			//flatIndex := osmconf.GetOsmConf().IndexByNodeId(id)
			flatIndex := osmconf.GetOsmConf().IndexByNodeId(grpIdStr, id)
			if IsHaming(oldKnowList, uint64(flatIndex)) || mpcServer.HaveSntMsg(hash, &id) {
				log.SyslogDebug("BroadcastMessage successfully(HaveSntMsg)", "isTransfer", isTransfer, "index", index, "peer", id.SlimString(), "msg", mpcMsg.String())
				haveSntIdps = append(haveSntIdps, &tempId)
				continue
			}

			SendIdps = append(SendIdps, &tempId)
			go func(id discover.NodeID, index int) {
				err := mpcServer.P2pMessager.SendToPeer(&id, code, msg)
				if err != nil {
					log.SyslogErr("BroadcastMessage fail", "peer", id.SlimString(), "err", err.Error())
					//time.Sleep(time.Millisecond * time.Duration(rand.Intn(20)))
					err2 := mpcServer.P2pMessager.SendToPeer(&id, code, msg)
					if err2 != nil {
						log.SyslogErr("BroadcastMessage fail again", "peer", id.SlimString(), "err", err.Error())
					} else {
						log.SyslogInfo("BroadcastMessage successfully(retry)", "isTransfer", isTransfer, "index", index, "peer", id.SlimString(), "msg", mpcMsg.String())
						mpcServer.AddSntMsg(hash, &id)
						//mpcServer.updateMsgKnownPeerIds(mpcMsg)
					}
				} else {
					// sent successfully and update the sntMsg to prevent send msg again.
					if isTransfer {
						log.SyslogInfo("BroadcastMessage successfully", "isTransfer", isTransfer, "index", index, "peer", id.SlimString(), "msg", mpcMsgStr)
					} else {
						log.SyslogDebug("BroadcastMessage successfully", "isTransfer", isTransfer, "index", index, "peer", id.SlimString(), "msg", mpcMsg.String())
					}
					mpcServer.AddSntMsg(hash, &id)
					//mpcServer.updateMsgKnownPeerIds(mpcMsg)
				}
			}(id, index)
		}
	}

	log.SyslogInfo("BroadcastMessage SendToPeer",
		" isTransfer", isTransfer,
		" toPeer have sent", discover.ArrNodeIdpsToStr(haveSntIdps),
		" toPeer send", discover.ArrNodeIdpsToStr(SendIdps),
		"mpcMessasge", mpcMsg.String())

	return nil
}

func (mpcServer *MpcDistributor) FreshPeer(nodes *[]discover.NodeID) error {

	defer mpcServer.mu.Unlock()
	mpcServer.mu.Lock()

	mpcServer.StoreManGroup = make([]discover.NodeID, len(*nodes))
	for i, item := range *nodes {
		mpcServer.StoreManGroup[i] = item
	}
	return nil
}

func (mpcServer *MpcDistributor) newStoremanKeyStore(pKey *ecdsa.PublicKey,
	pShare *big.Int,
	seeds []uint64,
	passphrase string,
	accType string) (accounts.Account, error) {

	ks := mpcServer.AccountManager.Backends(keystore.KeyStoreType)[0].(*keystore.KeyStore)
	account, err := ks.NewStoremanAccount(pKey, pShare, seeds, passphrase, accType)
	if err != nil {
		log.SyslogErr("NewStoremanKeyStore fail", "err", err.Error())
	} else {
		log.SyslogInfo("newStoremanKeyStore success", "addr", account.Address.String())
	}

	return account, err
}

func (mpcServer *MpcDistributor) CreateKeystore(result mpcprotocol.MpcResultInterface,
	peers *[]mpcprotocol.PeerInfo,
	accType string) error {

	log.SyslogInfo("MpcDistributor.CreateKeystore begin")
	point, err := result.GetValue(mpcprotocol.PublicKeyResult)
	if err != nil {
		log.SyslogErr("CreateKeystore fail. get PublicKeyResult fail")
		return err
	}

	private, err := result.GetValue(mpcprotocol.MpcPrivateShare)
	if err != nil {
		log.SyslogErr("CreateKeystore fail. get MpcPrivateShare fail")
		return err
	}

	result1 := new(ecdsa.PublicKey)
	result1.Curve = crypto.S256()
	result1.X = big.NewInt(0).SetBytes(point[0].Bytes())
	result1.Y = big.NewInt(0).SetBytes(point[1].Bytes())
	seed := make([]uint64, len(*peers))

	for i, item := range *peers {
		seed[i] = item.Seed
	}

	_, err = mpcServer.newStoremanKeyStore(result1, &private[0], seed, mpcServer.password, accType)
	if err != nil {
		return err
	}

	result.SetByteValue(mpcprotocol.MpcContextResult, crypto.FromECDSAPub(result1))
	log.Info("CreateKeystore ",
		"gpk address", crypto.PubkeyToAddress(*result1),
		"gpk hexutil.Encode", hexutil.Encode(crypto.FromECDSAPub(result1)))

	return nil
}

///////add for Btc begin

func (mpcServer *MpcDistributor) createMPCTxSigner(ChainType string, ChainID *big.Int) (mpccrypto.MPCTxSigner, error) {
	log.SyslogInfo("MpcDistributor.createMPCTxSigner begin", "ChainType", ChainType, "ChainID", ChainID.Int64())

	if ChainType == "WAN" {
		return mpccrypto.CreateWanMPCTxSigner(ChainID), nil
	} else if ChainType == "ETH" {
		return mpccrypto.CreateEthMPCTxSigner(ChainID), nil
	}

	return nil, mpcprotocol.ErrChainTypeError
}

func (mpcServer *MpcDistributor) createRequestMpcContextBtc(ctxType int, preSetValue ...MpcValue) (*mpcprotocol.SignedResult, []byte, error, uint64) {
	log.SyslogInfo("MpcDistributor createRequestMpcContextBtc begin")
	mpcID, err := mpcServer.getMpcID()
	if err != nil {
		return nil, nil, err, 0
	}

	peers := []mpcprotocol.PeerInfo{}

	var grpIdStr string
	for _, item := range preSetValue {
		if item.Key == ("MpcGrpId") {
			grpIdStr = hexutil.Encode(item.ByteValue)
			break
		}
	}

	var curveType uint8
	for _, item := range preSetValue {
		if item.Key == mpcprotocol.MpcCurve {
			curveBig := big.NewInt(0).SetBytes(item.ByteValue)
			curveType = uint8(curveBig.Uint64())
			break
		}
	}

	var smpc mpcprotocol.SchnorrMPCer
	switch int(curveType) {
	case mpcprotocol.SK256Curve:
		smpc = schnorrmpc.NewSkSchnorrMpc()
	case mpcprotocol.BN256Curve:
		smpc = schnorrmpcbn.NewBnSchnorrMpc()
	default:
		smpc = schnorrmpc.NewSkSchnorrMpc()
	}

	var address common.Address
	var gpkString string
	if ctxType == mpcprotocol.MpcSignLeaderBtc {
		for _, item := range preSetValue {
			if item.Key == mpcprotocol.MpcGpkBytes {
				pt, err := smpc.UnMarshPt(item.ByteValue)
				if err != nil {
					log.SyslogErr("createRequestMpcContext", "UnMarshPt error", err.Error())

					if !schcomm.PocTest {
						return nil, nil, err, mpcID
					}
				}
				//address, err = schnorrmpc.PkToAddress(item.ByteValue)
				address, err = smpc.PtToAddress(pt)
				if err != nil {
					log.SyslogErr("createRequestMpcContext", "PtToAddress error", err.Error())

					if !schcomm.PocTest {
						return nil, nil, err, mpcID
					}
				}
				gpkString = hexutil.Encode(item.ByteValue)
				break
			}
		}

		if schcomm.PocTest {
			b, _ := osmconf.GetOsmConf().GetPrivateShareMock(curveType)

			value := &MpcValue{mpcprotocol.MpcPrivateShare, []big.Int{b}, nil}
			// mpc private share
			preSetValue = append(preSetValue, *value)
		} else {
			addr := common.HexToAddress(gpkString)
			//value, err := mpcServer.loadStoremanAddress(curveType, gpkString, &address)
			value, err := mpcServer.loadStoremanAddress(curveType, gpkString, &addr)
			if err != nil {

				log.SyslogErr("MpcDistributor createRequestMpcContext, loadStoremanAddress fail",
					"address", address.String(),
					"err", err.Error())

				return nil, nil, err, mpcID
			}

			// mpc private share
			preSetValue = append(preSetValue, *value)
		}
	}

	peers, err = osmconf.GetOsmConf().GetPeersByGrpId(grpIdStr)
	if err != nil {
		log.SyslogErr("createRequestMpcContext", "GetPeersByGrpId", err.Error())
		return nil, nil, err, mpcID
	}
	//groupAlivePeersCount := uint16(len(groupAlivePeers))
	groupAlivePeersCount, _ := osmconf.GetOsmConf().GetTotalNum(grpIdStr)
	mpc, err := mpcServer.mpcCreater.CreateContext(ctxType,
		mpcID,
		peers,
		groupAlivePeersCount-1,
		curveType,
		preSetValue...)
	if err != nil {
		log.SyslogErr("MpcDistributor createRequestMpcContext, CreateContext fail", "err", err.Error())
		return nil, nil, err, mpcID
	}

	log.SyslogInfo("MpcDistributor createRequestMpcContext", "ctxType", ctxType, "mpcID", mpcID)

	mpcServer.addMpcContext(mpcID, mpc)
	defer mpcServer.removeMpcContext(mpcID)
	err = mpc.mainMPCProcess(mpcServer)

	ret, err2 := mpc.getMpcResult(err)
	if err2 != nil {
		log.SyslogErr("MpcDistributor createRequestMpcContext", "getMpcResult", err2.Error())
		return nil, nil, err2, mpcID
	}

	r, ok := ret.(mpcprotocol.SignedResult)
	if !ok {
		log.SyslogErr("MpcDistributor createRequestMpcContext", "getMpcResult: type is not SignedResult, type is", reflect.TypeOf(r))
		return nil, nil, errors.New("getMpcResult return type convert failed"), mpcID
	}
	value, err := mpc.(*MpcContext).mpcResult.GetByteValue(mpcprotocol.MpcContextResult)

	return &r, value, err, mpcID

}

func (mpcServer *MpcDistributor) CreateRequestBtcMpcSign(args *btc.MsgTxArgs, byApprove int64) (*mpcprotocol.SignedSuccResult, uint64, error) {
	log.SyslogInfo("CreateRequestBtcMpcSign begin")

	grpId, _ := osmconf.GetOsmConf().GetGrpInxByGpk(args.From)
	grpIdBytes, _ := hexutil.Decode(grpId)

	txBytesData, err := rlp.EncodeToBytes(args)
	if err != nil {
		log.SyslogErr("CreateRequestBtcMpcSign, rlp encode tx fail", "err", err.Error())
		return nil, 0, err
	}

	txHashes, err := btc.GetHashedForEachTxIn(args)
	if err != nil {
		return nil, 0, err
	}

	preSetValues := []MpcValue{}
	for i := 0; i < len(args.TxIn); i++ {
		preSetValues = append(preSetValues, MpcValue{mpcprotocol.MpcTxHash + "_" + strconv.Itoa(i), []big.Int{*txHashes[i].Big()}, nil})
	}

	preSetValues = append(preSetValues, MpcValue{mpcprotocol.MpcAddress, []big.Int{*args.FromAddr().Big()}, nil})
	preSetValues = append(preSetValues, MpcValue{mpcprotocol.MpcTransaction, nil, txBytesData})
	preSetValues = append(preSetValues, MpcValue{mpcprotocol.MpcChainType, nil, []byte("BTC")})
	preSetValues = append(preSetValues, MpcValue{mpcprotocol.MpcSignType, nil, []byte("hash")})

	preSetValues = append(preSetValues, MpcValue{mpcprotocol.MpcByApprove, []big.Int{*(big.NewInt(byApprove))}, nil})

	preSetValues = append(preSetValues, MpcValue{"MpcGrpId", nil, grpIdBytes})
	preSetValues = append(preSetValues, MpcValue{mpcprotocol.MpcGpkBytes, nil, args.From[:]})

	// Now btc use SK256Curve, if BTC use other curve, we should change the parameter of SignMpcBtcTransaction.
	preSetValues = append(preSetValues, MpcValue{mpcprotocol.MpcCurve, nil, []byte{mpcprotocol.SK256Curve}})

	signResult, value, err, mpcId := mpcServer.createRequestMpcContextBtc(mpcprotocol.MpcSignLeaderBtc, preSetValues...)
	if err != nil {
		return nil, mpcId, err
	}

	ret := make([]hexutil.Bytes, 0, len(args.TxIn))
	pot := 0
	for pot < len(value) {
		ret = append(ret, value[pot+1:pot+1+int(value[pot])])
		pot += int(value[pot]) + 1
	}
	log.SyslogInfo("CreateReqMpcSign begin", "mpcId", mpcId, "@@@@@data for sigin Btc", args.String())
	log.SyslogInfo("CreateRequestBtcMpcSign", "value", value, "ret", ret, "mpcId", mpcId)
	r := &mpcprotocol.SignedSuccResult{SignedResult: *signResult, SignedBtc: ret}

	return r, mpcId, nil
}

func (mpcServer *MpcDistributor) SignTransaction(result mpcprotocol.MpcResultInterface, signNum int, ctx uint64) error {

	chainType, err1 := result.GetByteValue(mpcprotocol.MpcChainType)
	log.SyslogInfo("MpcDistributor.SignTransaction begin", "signNum", signNum, "chainType", string(chainType))

	//TODO: signTransaction for Polkadot tx by liulin
	if bytes.Equal(chainType, []byte("BTC")) {
		txSigns := make([]byte, 0)
		var signFrom *common.Address

		for i := 0; i < signNum; i++ {
			iStr := "_" + strconv.Itoa(i)

			R, err := result.GetValue(mpcprotocol.MpcTxSignResultR + iStr)
			if err != nil {
				return err
			}

			V, err := result.GetValue(mpcprotocol.MpcTxSignResultV + iStr)
			if err != nil {
				return err
			}

			S, err := result.GetValue(mpcprotocol.MpcTxSignResult + iStr)
			if err != nil {
				return err
			}

			sinature := btcec.Signature{&R[0], &S[0]}
			sign := sinature.Serialize()
			txSigns = append(txSigns, byte(len(sign)+1))
			txSigns = append(txSigns, sign...)
			txSigns = append(txSigns, byte(txscript.SigHashAll))

			txHash, err := result.GetValue(mpcprotocol.MpcTxHash + iStr)
			if err != nil {
				return err
			}
			//TODO: recover public address from signature to verify not recover address   by liulin
			signFromTmp, err := btc.RecoverPublicKey(common.BytesToHash(txHash[0].Bytes()), &R[0], &S[0], &V[0])
			log.SyslogInfo("SignTransaction", "txHash", txHash[0].String(), "R", R[0].String(), "S", S[0].String(), "V", V[0].String(), "ctx", ctx)
			if err != nil {
				return err
			} else if signFrom == nil {
				signFrom = &signFromTmp
			} else if (*signFrom) != signFromTmp {
				log.SyslogErr("MpcDistributor.SignTransaction, signfrom doesn't match pre value",
					"pre", signFrom.String(), "this", signFromTmp.String())
				return mpcprotocol.ErrRecoverPkNotMatchPre
			}
		}

		result.SetByteValue(mpcprotocol.MPCSignedFrom, (*signFrom)[:])
		result.SetByteValue(mpcprotocol.MpcContextResult, txSigns)
		log.SyslogInfo("MpcDistributor.SignTransaction, "+mpcprotocol.MpcContextResult, "signs", common.ToHex(txSigns))
		return nil

	} else {

		R, err := result.GetValue(mpcprotocol.MpcTxSignResultR + "_0")
		if err != nil {
			log.SyslogErr("MpcDistributor.SignTransaction, GetValue fail", "key", mpcprotocol.MpcTxSignResultR)
			return err
		}

		V, err := result.GetValue(mpcprotocol.MpcTxSignResultV + "_0")
		if err != nil {
			log.SyslogErr("MpcDistributor.SignTransaction, GetValue fail", "key", mpcprotocol.MpcTxSignResultV)
			return err
		}

		S, err := result.GetValue(mpcprotocol.MpcTxSignResult + "_0")
		if err != nil {
			log.SyslogErr("MpcDistributor.SignTransaction, GetValue fail", "key", mpcprotocol.MpcTxSignResult)
			return err
		}

		SignType, err := result.GetByteValue(mpcprotocol.MpcSignType)
		if (err == nil && bytes.Equal(SignType, []byte("hash"))) || err1 != nil {
			txSign, err := mpccrypto.TransSignature(&R[0], &S[0], &V[0])
			if err != nil {
				log.SyslogErr("mpccrypto tans signature fail", "err", err.Error())
				return err
			}

			result.SetByteValue(mpcprotocol.MpcContextResult, txSign)
			txHash, err := result.GetValue(mpcprotocol.MpcTxHash + "_0")
			if err == nil {
				from, err := mpccrypto.SenderEcrecover(common.BytesToHash(txHash[0].Bytes()).Bytes(), txSign)
				if err != nil {
					log.SyslogErr("MpcDistributor.SignTransaction, SenderEcrecover fail", "err", err.Error())
				} else {
					result.SetByteValue(mpcprotocol.MPCSignedFrom, from[:])
				}
			}

			return nil

		} else {
			chianID, err := result.GetValue(mpcprotocol.MpcChainID)
			if err != nil {
				log.SyslogErr("MpcDistributor.SignTransaction, GetValue fail", "key", mpcprotocol.MpcChainID)
				return err
			}

			signer, err := mpcServer.createMPCTxSigner(string(chainType[:]), &chianID[0])
			if err != nil {
				log.SyslogErr("MpcDistributor.SignTransaction, create mpc signer fail", "err", err.Error())
				return err
			}

			encodedTx, err := result.GetByteValue(mpcprotocol.MpcTransaction)
			if err != nil {
				log.SyslogErr("MpcDistributor.SignTransaction, GetValue fail", "key", mpcprotocol.MpcTransaction)
				return err
			}

			tx := new(types.Transaction)
			if err := rlp.DecodeBytes(encodedTx, tx); err != nil {
				log.SyslogErr("rlp decode fail", "err", err.Error())
				return err
			}

			txSign, from, err := signer.SignTransaction(tx, &R[0], &S[0], &V[0])
			if err != nil {
				log.SyslogErr("mpc signatual fail", "err", err.Error())
				return err
			}

			result.SetByteValue(mpcprotocol.MpcContextResult, txSign)
			result.SetByteValue(mpcprotocol.MPCSignedFrom, from[:])
			return nil
		}
	}

}

///////add for Btc End
func (mpcServer *MpcDistributor) CreateRequestXrpMpcSign(args mpcprotocol.SendEcData, byApprove int64) (*mpcprotocol.SignedDataResult, uint64, error) {
	log.SyslogInfo("CreateRequestXrpMpcSign begin")

	grpId, _ := osmconf.GetOsmConf().GetGrpInxByGpk(args.PKBytes[:])
	grpIdBytes, _ := hexutil.Decode(grpId)
	addr := common.BytesToAddress(crypto.Keccak256(args.PKBytes)[12:]) //FromAddr(args.From)
	xrpHandler, err := validator.GetXrpHandler(args.TxHash, []byte(args.TxData))
	if err != nil {
		return nil, 0, err
	}
	dataHashs := xrpHandler.GetHashedData()
	dataHash := common.BytesToHash(dataHashs[0])
	chianID := dataHash // TODO need this one?

	preSetValues := []MpcValue{}
	preSetValues = append(preSetValues, MpcValue{mpcprotocol.MpcTxHash + "_0", []big.Int{*dataHash.Big()}, nil})
	preSetValues = append(preSetValues, MpcValue{mpcprotocol.MpcAddress, []big.Int{*addr.Big()}, nil})
	preSetValues = append(preSetValues, MpcValue{mpcprotocol.MpcTransaction, nil, []byte(args.TxData)})
	preSetValues = append(preSetValues, MpcValue{mpcprotocol.MpcChainType, nil, []byte(args.ChainType)})
	preSetValues = append(preSetValues, MpcValue{mpcprotocol.MpcSignType, nil, []byte("hash")})
	preSetValues = append(preSetValues, MpcValue{mpcprotocol.MpcChainID, []big.Int{*chianID.Big()}, nil}) // TODO remove chainId???
	preSetValues = append(preSetValues, MpcValue{mpcprotocol.MpcByApprove, []big.Int{*(big.NewInt(byApprove))}, nil})
	preSetValues = append(preSetValues, MpcValue{"MpcGrpId", nil, grpIdBytes})
	preSetValues = append(preSetValues, MpcValue{mpcprotocol.MpcGpkBytes, nil, args.PKBytes[:]})
	preSetValues = append(preSetValues, MpcValue{mpcprotocol.MpcCurve, nil, []byte{mpcprotocol.SK256Curve}})
	signResult, value, err, mpcId := mpcServer.createRequestMpcContextBtc(mpcprotocol.MpcSignLeaderBtc, preSetValues...)
	if err != nil {
		return nil, 0, err
	}
	R := new(big.Int).SetBytes(value[0:32])
	S := new(big.Int).SetBytes(value[32:64])
	sinature := btcec.Signature{R, S}
	der := sinature.Serialize()
	log.SyslogInfo("CreateRequestXrpMpcSign ", "mpcId", mpcId, "@@@@@data for sigin Xrp", args.String())
	log.SyslogInfo("CreateRequestXrpMpcSign", "value", value, "mpcId", mpcId)

	r := &mpcprotocol.SignedDataResult{SignedResult: *signResult, SignedData: der}

	return r, mpcId, nil
}

func (mpcServer *MpcDistributor) CreateRequestDotMpcSign(args mpcprotocol.SendEcData, byApprove int64) (*mpcprotocol.SignedDataResult, uint64, error) {
	log.SyslogInfo("CreateRequestBtcMpcSign begin", "ags", args.String())

	grpId, _ := osmconf.GetOsmConf().GetGrpInxByGpk(args.PKBytes[:])
	grpIdBytes, _ := hexutil.Decode(grpId)
	addr := common.BytesToAddress(crypto.Keccak256(args.PKBytes)[12:]) //FromAddr(args.From)
	//txHashes := args.TxHash
	dataHash := common.BytesToHash(args.TxHash)

	preSetValues := []MpcValue{}
	preSetValues = append(preSetValues, MpcValue{mpcprotocol.MpcTxHash + "_0", []big.Int{*dataHash.Big()}, nil})

	tranData, error := json.Marshal(args)
	if error != nil {
		return nil, 0, error
	}

	preSetValues = append(preSetValues, MpcValue{mpcprotocol.MpcAddress, []big.Int{*addr.Big()}, nil})
	preSetValues = append(preSetValues, MpcValue{mpcprotocol.MpcTransaction, nil, tranData})
	preSetValues = append(preSetValues, MpcValue{mpcprotocol.MpcChainType, nil, []byte(args.ChainType)})
	preSetValues = append(preSetValues, MpcValue{mpcprotocol.MpcSignType, nil, []byte("hash")})
	preSetValues = append(preSetValues, MpcValue{mpcprotocol.MpcChainID, []big.Int{*dataHash.Big()}, nil}) // TODO remove chainId???
	preSetValues = append(preSetValues, MpcValue{mpcprotocol.MpcByApprove, []big.Int{*(big.NewInt(byApprove))}, nil})

	preSetValues = append(preSetValues, MpcValue{"MpcGrpId", nil, grpIdBytes})
	preSetValues = append(preSetValues, MpcValue{mpcprotocol.MpcGpkBytes, nil, args.PKBytes[:]})

	// Now btc use SK256Curve, if BTC use other curve, we should change the parameter of SignMpcBtcTransaction.
	preSetValues = append(preSetValues, MpcValue{mpcprotocol.MpcCurve, nil, []byte{mpcprotocol.SK256Curve}})

	signResult, value, err, mpcId := mpcServer.createRequestMpcContextBtc(mpcprotocol.MpcSignLeaderBtc, preSetValues...)
	if err != nil {
		return nil, 0, err
	}

	ret := make([]byte, 66)
	ret[0] = 0x02
	copy(ret[1:], value[:])
	log.SyslogInfo("CreateRequestDotMpcSign ", "mpcId", mpcId, "@@@@@data for sigin DOT", args.String())
	log.SyslogInfo("CreateRequestDotMpcSign", "value", value, "mpcId", mpcId)

	r := &mpcprotocol.SignedDataResult{SignedResult: *signResult, SignedData: ret}

	return r, mpcId, nil

}

///// add for uniMpc
func (mpcServer *MpcDistributor) CreateReqMpcSignUni(input *mpcprotocol.SignInput, byApprove int64) (interface{}, error, uint64) {

	log.SyslogInfo("CreateReqMpcSignUni begin")
	grpId, _ := osmconf.GetOsmConf().GetGrpInxByGpk(input.PKBytes)

	// MpcGpkBytes stores the gpk bytes.
	grpIdBytes, _ := hexutil.Decode(grpId)
	value, err, mpcID := mpcServer.createRequestMpcContextUni(
		mpcprotocol.MpcSignLeaderUni,
		input,
		MpcValue{"MpcGrpId", nil, grpIdBytes},
		MpcValue{mpcprotocol.MpcGpkBytes, nil, input.PKBytes[:]},
		MpcValue{mpcprotocol.MpcByApprove, []big.Int{*(big.NewInt(byApprove))}, nil},
	)

	log.SyslogInfo("CreateReqMpcSignUni begin", "ctx", mpcID, "@@@@@data for SignByApprove", input.String())
	return value, err, mpcID
}

func (mpcServer *MpcDistributor) NeedDrop() (error, bool) {
	mpcServer.mu.Lock()
	lenCtx := len(mpcServer.mpcMap)
	mpcServer.mu.Unlock()
	log.SyslogInfo("MpcDistributor::NeedDrop", "current length of ctx", lenCtx, "max length of ctx", mpcprotocol.MaxMpcContext)
	if lenCtx >= mpcprotocol.MaxMpcContext {
		return errors.New("the sigByApprove is dropped because of system capacity"), true
	}
	return nil, false
}

func (mpcServer *MpcDistributor) createRequestMpcContextUni(ctxType int, input *mpcprotocol.SignInput, preSetValue ...MpcValue) (interface{}, error, uint64) {
	mpcID, err := mpcServer.getMpcID()
	if err != nil {
		return nil, err, 0
	}
	log.SyslogInfo("MpcDistributor createRequestMpcContextUni begin", "ctx", mpcID)
	peers := []mpcprotocol.PeerInfo{}

	var grpIdStr string
	for _, item := range preSetValue {
		if item.Key == ("MpcGrpId") {
			grpIdStr = hexutil.Encode(item.ByteValue)
			break
		}
	}

	var curveType uint8
	curveBig := big.NewInt(0).SetBytes(input.Curve)
	curveType = uint8(curveBig.Uint64())

	var smpc mpcprotocol.SchnorrMPCer
	switch int(curveType) {
	case mpcprotocol.SK256Curve:
		smpc = schnorrmpc.NewSkSchnorrMpc()
	case mpcprotocol.BN256Curve:
		smpc = schnorrmpcbn.NewBnSchnorrMpc()
	default:
		smpc = schnorrmpc.NewSkSchnorrMpc()
	}

	var alg uint8
	algBig := big.NewInt(0).SetBytes(input.Alg)
	alg = uint8(algBig.Uint64())

	var address common.Address
	var gpkString string
	if ctxType == mpcprotocol.MpcSignLeaderUni {

		pt, err := smpc.UnMarshPt(input.PKBytes)
		if err != nil {
			log.SyslogErr("createRequestMpcContext", "UnMarshPt error", err.Error())

			if !schcomm.PocTest {
				return []byte{}, err, 0
			}
		}
		//address, err = schnorrmpc.PkToAddress(item.ByteValue)
		address, err = smpc.PtToAddress(pt)
		if err != nil {
			log.SyslogErr("createRequestMpcContext", "PtToAddress error", err.Error())

			if !schcomm.PocTest {
				return []byte{}, err, 0
			}
		}
		gpkString = hexutil.Encode(input.PKBytes)

		if schcomm.PocTest {
			b, _ := osmconf.GetOsmConf().GetPrivateShareMock(curveType)

			value := &MpcValue{mpcprotocol.MpcPrivateShare, []big.Int{b}, nil}
			// mpc private share
			preSetValue = append(preSetValue, *value)
		} else {
			addr := common.HexToAddress(gpkString)
			//value, err := mpcServer.loadStoremanAddress(curveType, gpkString, &address)
			value, err := mpcServer.loadStoremanAddress(curveType, gpkString, &addr)
			if err != nil {

				log.SyslogErr("MpcDistributor createRequestMpcContextUni, loadStoremanAddress fail",
					"address", address.String(),
					"err", err.Error())

				return []byte{}, err, 0
			}

			// mpc private share
			preSetValue = append(preSetValue, *value)

			// mpc private share inverse
			skInverse, _ := smpc.NSubX(&value.Value[0])
			valueInverse := &MpcValue{mpcprotocol.MpcPrivateShareInverse, []big.Int{*skInverse}, nil}
			preSetValue = append(preSetValue, *valueInverse)
		}
	}

	peers, err = osmconf.GetOsmConf().GetPeersByGrpId(grpIdStr)
	if err != nil {
		log.SyslogErr("createRequestMpcContextUni", "GetPeersByGrpId", err.Error())
		return nil, err, 0
	}
	groupAlivePeersCount, _ := osmconf.GetOsmConf().GetTotalNum(grpIdStr)
	mpc, err := mpcServer.mpcCreater.CreateContextUni(ctxType,
		mpcID,
		peers,
		groupAlivePeersCount-1,
		curveType,
		alg,
		input,
		preSetValue...)

	if err != nil {
		log.SyslogErr("MpcDistributor createRequestMpcContextUni, CreateContext fail", "err", err.Error())
		return []byte{}, err, 0
	}

	log.SyslogInfo("MpcDistributor createRequestMpcContextUni", "ctxType", ctxType, "mpcID", mpcID)
	//err, needDrop := mpcServer.needDrop()
	//if needDrop {
	//	return nil, err, mpcID
	//}
	mpcServer.addMpcContext(mpcID, mpc) //todo add throat to handle burst traffic
	defer mpcServer.removeMpcContext(mpcID)
	err = mpc.mainMPCProcess(mpcServer)

	ret, err := mpc.getMpcResultUni(err, len(input.HashData))
	return ret, err, mpcID
}

//// add for two layer index (flat node index => two layer index)
func (mpcServer *MpcDistributor) GetGrpIdByCtxId(ctxId uint64) (string, error) {
	mpcServer.mu.RLock()
	defer mpcServer.mu.RUnlock()
	if ctx, exist := mpcServer.mpcMap[ctxId]; exist {
		_, grpIdStr, err := ctx.GetGrpIdByCtx()
		return grpIdStr, err
	}
	return "", fmt.Errorf("mpc is not exist")
}
